﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Text;
using System.Web;
using System.Web.UI;


namespace HDI.Charts2
{
    public class Gantt : Chart
    {
        #region Member


        public DateTime _start, _end;
        protected String legend = "";
        protected int actColor = 0;
        private bool _sort = false;
        protected List<string> Color = new List<string>();
        private bool onRender = false;

        //GROUPINFO
        public string GroupInfoDataField = "";
        /// <summary>
        /// Possible Values are:
        /// "sum", "count", "min", "max"
        /// </summary>
        public string GroupInfoType = "count";

        public string GroupInfoFormat = " ({0})";

        /// <summary>
        /// Provvides the first date to Display
        /// </summary>
        public DateTime Start
        {
            get
            {
                DateTime minDate = (from d in this.Daten from c in d select c["Start"].ToDate()).Min();

                return Helper.gotoDayOfWeek(minDate, DayOfWeek.Monday);
            }

        }

        /// <summary>
        /// provides the last date to display; 
        /// </summary>
        public DateTime End
        {
            get
            {
                return Helper.gotoDayOfWeek((from d in this.Daten from c in d select c["End"].ToDate()).Max(), DayOfWeek.Sunday);
            }

        }

        public String Culture = "de-DE";


        public int Weeks
        {
            get
            {
                double weeks = (this.End.AddDays(1).Subtract(this.Start).Days / 7);
                return (int)Math.Floor(weeks);
            }

        }

        #endregion

        #region Kostruktor
        public Gantt(string Name)
            : base(Name)
        {
            defaultColor();


        }

        //public Gantt(string Name, DateTime Start)
        //    : base(Name)
        //{
        //    defaultColor();
        //    this.Start = Start;
        //    this.Weeks = 7;

        //}

        //public Gantt(string Name, DateTime Start, int Weeks)
        //    : base(Name)
        //{
        //    defaultColor();
        //    this.Start = Start;
        //    this.Weeks = Weeks;

        //}

        //public Gantt(string Name, DateTime Start, DateTime End)
        //    : base(Name)
        //{
        //    defaultColor();
        //    this.Start = Start;
        //    this.End = End;
        //}

        #endregion

        public Data addData(int series, string Title, string Start, string End, string Color, string Overlay, string Tooltip, string Search)
        {
            Data tmp = this.Daten[series].addData(Title);
            tmp.Add("Start", Start);
            tmp.Add("End", End);
            tmp.Add("Color", Color);
            tmp.Add("Overlay", Overlay);
            tmp.Add("Tooltip", Tooltip);
            tmp.Add("Search", Search);
            return tmp;
        }


        public Data addData(int series, string Title, string Start, String End)
        {
            string color = Daten[series].Option["Color"];
            return this.addData(series, Title, Start, End, color, "", "", Title);
        }


        public void sort()
        {
            _sort = true;
        }
        private Series sortSerie(Series serie)
        {
            serie.Sort((x, y) => DateTime.Compare(x["Start"].ToDate(), y["Start"].ToDate()));
            return serie;
        }

        public override void init()
        {
            JS = Dateien.HDIGantt;
            CSS = Dateien.HDIGanttCss;
        }

        public Series addSeries(string Name, String Color)
        {
            Series tmp = base.addSeries(Name);
            this.Daten.Last().setOption("Color", Color);
            return tmp;
        }

        public override Series addSeries(string Name)
        {
            return this.addSeries(Name, getColor());
        }

        public string getColor()
        {
            actColor++;
            if (actColor < this.Color.Count)
            {
                return this.Color[actColor - 1];
            }
            return "#123456";
        }

        public override string getHTML()
        {
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(this.Culture);
            System.Globalization.CultureInfo myCI = new System.Globalization.CultureInfo(this.Culture);

            StringBuilder _html = new StringBuilder();

            if (useDatepicker == true)
            {
                setDatepicker();
            }
            if (useLegend == true)
            {
                setLegend();
            }
            if (useSearch == true)
            {
                setSearch();
            }
            //defining Controls
            _html.Append("<div id=\"" + ClientID + "Diagramm\" class='Gantt'><h2>"+this.Title+"</h2>" + this.legend + this.search + this.datepicker + "<div style='clear:both'></div><table style='border-collapse: collapse;width:" + (Weeks * 18 * 7 + 100) + "px;  '><tr class='ganttWeeks'><td rowspan='2'  style='width: 100px; '></td>");

            //defining head
            for (int j = 0; j < Weeks; j++)
            {
                int week = myCI.Calendar.GetWeekOfYear(this.Start.AddDays(7 * j), System.Globalization.CalendarWeekRule.FirstFourDayWeek, System.DayOfWeek.Monday);
                _html.Append("<td colspan='7'><b>" + this.Start.AddDays(7 * j).ToShortDateString() + "</b><br/>KW " + week + "</td>");
            }

            _html.Append("</tr><tr class='ganttDays'>");
            for (int j = 0; j < Weeks; j++)
            {
                DateTime week = this.Start.AddDays(7 * j);
                _html.Append("<td style='width: 16px;' date='" + week.ToString("yyyy-MM-dd") + "'>Mo</td><td style='width: 16px;' date='" + week.AddDays(1).ToString("yyyy-MM-dd") + "'>Di</td><td style='width: 16px;' date='" + week.AddDays(2).ToString("yyyy-MM-dd") + "'>Mi</td><td style='width: 16px;' date='" + week.AddDays(3).ToString("yyyy-MM-dd") + "'>Do</td><td style='width: 16px;' date='" + week.AddDays(4).ToString("yyyy-MM-dd") + "'>Fr</td><td style='background: #eee;width: 16px;' date='" + week.AddDays(5).ToString("yyyy-MM-dd") + "'>Sa</td><td style='width: 16px;background: #eee;' date='" + week.AddDays(6).ToString("yyyy-MM-dd") + "'>So</td>");
            }
            _html.Append("</tr>");
            string we;
            string date;
            StringBuilder Duration = new StringBuilder();
            foreach (Series sers in this.Daten)
            {
                if (_sort)
                {
                    sortSerie(sers);
                }
                if (this.Daten.Count > 1)
                {
                    DateTime firstDate = sers.Min(x => x["Start"].ToDate());
                    DateTime lastDate = sers.Max(x => x["End"].ToDate());
                    Duration.Append("<tr class='groupGantt opened' serie='" + sers.FName + "' startDate='" + firstDate.ToString("yyyy-MM-dd") + "' endDate='" + lastDate.ToString("yyyy-MM-dd") + "'><td class='WPname'><span>" + sers.Name + getGroupInfo(sers) + "</span></td>");
                    for (int currentDay = 0; currentDay < Weeks * 7; currentDay++)
                    {
                        string round = "", sDot = "";
                        if (currentDay == 0 || currentDay == Weeks * 7 - 1)
                        {
                            if (lastDate < Start && currentDay == 0)
                            {
                                sDot = "&laquo;";
                            }
                            else if (firstDate > End && currentDay == Weeks * 7 - 1)
                            {
                                sDot = "&raquo;";
                            }
                        }
                        string today = "";
                        if (this.Start.AddDays(currentDay).ToShortDateString() == DateTime.Today.ToShortDateString())
                        {
                            today = " ganttToday";
                        }

                        //check if Weekend
                        we = (((Helper.wochenTag(this.Start.AddDays(currentDay).DayOfWeek) == 5) || (Helper.wochenTag(this.Start.AddDays(currentDay).DayOfWeek) == 6)) ? " ganttWE" : "");

                        
                        if (this.Start.AddDays(currentDay) <= lastDate && this.Start.AddDays(currentDay) >= firstDate)
                        {
                            string overlay = "";
                            date = this.Start.AddDays(currentDay).ToString("yyyy-MM-dd");
                            if (firstDate == lastDate)
                            {
                                round = "border-radius: 4px 4px 4px 4px; ";
                                sDot = "";

                            }
                            else if (this.Start.AddDays(currentDay) == firstDate)
                            {
                                round = "border-radius: 4px 0 0 4px; ";
                                sDot = "";

                            }
                            else if (this.Start.AddDays(currentDay) == lastDate)
                            {
                                round = "border-radius: 0 4px 4px 0;";
                            }
                            


                            Duration.Append("<td class='value" + we + today+"'  date='" + date.Replace(".", "") + "' style='padding: 0px; " +
                                "'>" + overlay + "<div  style='" + round + "border-top: 2px solid " + sers.Option["Color"] + ";'>" + sDot + "</div></td>");
                        }
                        else
                        {
                            Duration.Append("<td class='" + we + today + "' >" + sDot + "</td>");
                        }

                    }
                    Duration.Append("</tr>");
                }


                foreach (Data data in sers)
                {
                    we = ""; date = "";
                    string color = "";
                    data.TryGetValue("Color", out color);
                    Duration.Append("<tr class='" + sers.FName + " "+color.Replace("#","")+"'  startDate='" + data["Start"] + "' endDate='" + data["End"] + "'><td  style='width:150px;  'class='WPname'>" + data.Name + "<span class='searchcontent'>" + data["Search"] + "</span></td>");
                    for (int currentDay = 0; currentDay < Weeks * 7; currentDay++)
                    {
                        we = (((Helper.wochenTag(this.Start.AddDays(currentDay).DayOfWeek) == 5) || (Helper.wochenTag(this.Start.AddDays(currentDay).DayOfWeek) == 6)) ? " ganttWE" : "");
                        string today = "";
                        if (this.Start.AddDays(currentDay).ToShortDateString() == DateTime.Today.ToShortDateString())
                        {
                            today = " ganttToday";
                        }
                        if (this.Start.AddDays(currentDay) <= data["End"].ToDate() && this.Start.AddDays(currentDay) >= data["Start"].ToDate())
                        {
                            string round = "", sDot = "";
                            string overlay = "";
                            date = this.Start.AddDays(currentDay).ToShortDateString();

                            if (data["Start"] == data["End"])
                            {
                                round = "border-radius: 4px 4px 4px 4px; ";
                                sDot = "&diams;";
                                overlay = "<div class='ganttOverlay' style='" + getOverlayColor(color) + "' >" + data["Overlay"] + "</div>";
                            }
                            else if (this.Start.AddDays(currentDay) == data["Start"].ToDate())
                            {
                                round = "border-radius: 4px 0 0 4px; ";
                                sDot = "&diams;";
                                overlay = "<div class='ganttOverlay' style='" + getOverlayColor(color) + "' >" + data["Overlay"] + "</div>";
                            }
                            else if (this.Start.AddDays(currentDay) == data["End"].ToDate())
                            {
                                round = "border-radius: 0 4px 4px 0;";
                            }
                            else if (currentDay == 0)
                            {
                                overlay = "<div class='ganttOverlay' style='" + getOverlayColor(color) + "' >" + data["Overlay"] + "</div>";
                            }

                            Duration.Append("<td class='value" + we + today+"'  startdate='" + date.Replace(".", "") + "'  title='" +
                              data["Tooltip"] +
                                "' style='padding: 0px; " +
                                "'>" + overlay + "<div class='ganttData' style='" + round + Helper.getColor(color) + "'>" + sDot + "</div></td>");
                        }
                        else
                        {
                            Duration.Append("<td class='" + we + today+"' ></td>");
                        }
                    }
                    Duration.Append("</tr>");
                    _html.Append(Duration);
                    Duration.Remove(0, Duration.Length);
                }
            }
            _html.Append("</table></div> ");
            this.html = _html.ToString();
            return this.html;
        }

        private string getGroupInfo(Series sers)
        {
            string info = "";
            if (!string.IsNullOrEmpty(this.GroupInfoDataField))
            {
                double x = 0;
                switch (this.GroupInfoType)
                {
                    case "sum":
                        foreach (Data Data in sers)
                        {
                            x += Double.Parse(Data[GroupInfoDataField]);
                        }
                        info = String.Format(this.GroupInfoFormat, x);
                        break;
                    case "min":
                        info = String.Format(this.GroupInfoFormat, sers.Min(d => Double.Parse(d[GroupInfoDataField])));
                        break;
                    case "max":
                        info = String.Format(this.GroupInfoFormat, sers.Max(d => Double.Parse(d[GroupInfoDataField])));
                        break;
                    case "count":
                    default:
                        info = String.Format(this.GroupInfoFormat, sers.Count);
                        break;
                }

            }

            return info;
        }


        protected string getOverlayColor(string hex)
        {
            Color col = ColorTranslator.FromHtml(hex);
            string nhex = "#fff";
            if (col.GetBrightness() > 0.5) nhex = "#000";
            else if (col.GetBrightness() == 0.5) nhex = "#808080";
            return "color: " + nhex + ";" + "z-index:" + col.GetBrightness().ToString();
        }

        private void defaultColor()
        {
            Color.Clear();
            Color.Add("#2d6291");
            Color.Add("#95ae35");

            Color.Add("#e68700");

            Color.Add("#8260b2");
            Color.Add("#68003e");

            Color.Add("#64ae4b");
            Color.Add("#383042");
            Color.Add("#6a4626");
            Color.Add("#bf3a00");
            Color.Add("#360");
            Color.Add("#f60");
            Color.Add("#0c0");
            Color.Add("#fc6");
            Color.Add("#006");
            Color.Add("#f66");
            Color.Add("#0c9");
            Color.Add("#00f");
            Color.Add("#f6f");
            Color.Add("#0cf");
            Color.Add("#030");
            Color.Add("#090");
            Color.Add("#0f0");
            Color.Add("#ff0");
            Color.Add("#036");
            Color.Add("#096");
            Color.Add("#0f6");
            Color.Add("#039");
            Color.Add("#099");
            Color.Add("#0f9");
            Color.Add("#03c");
            Color.Add("#0fc");
            Color.Add("#0ff");
            Color.Add("#000");
        }


        private string setLegend()
        {
            this.legend = "";
            StringBuilder options = new StringBuilder();
            if (this.Daten.Count > 1)
            {
                foreach (Series field in this.Daten)
                {
                    String Color = "";
                    Color = Helper.getColor(field.Option["Color"]);
                    options.Append("<li class='Colorfilter groupGantt' serie='" + field.FName + "'>" + field.Name + "<span style='" + Color + "'>&nbsp;</span></li>");
                }
            }
            else
            {
                List<string> colors = new List<string>();
                foreach (Data data in this.Daten[0])
                {
                    String color = "";
                    String group = "";
                    if (data.TryGetValue("Color", out color) && !colors.Contains(color) )
                    {
                        colors.Add(color);
                        data.TryGetValue("Group", out group);
                        options.Append("<li class='Colorfilter groupGantt' serie='" + color.Replace("#", "") + "'>"+group+"<span style='" + Helper.getColor(color) + "'>&nbsp;</span></li>");
                    }
                }
            }
            this.legend = String.Format("<div class=\"ganttlegend\"><h3>Legende</h3><ul>{0}</ul></div>", options.ToString());
            return this.legend;
        }

        private void setSearch()
        {

            this.search = "<div class='searchContainer'><h3>Suche:</h3><input type='text' class='ganttSearch'/></div>";
        }

        private void setDatepicker()
        {
            this.datepicker = "<div class='dateContainer'><h3>Datum</h3><input type='type' id='startdate' class='datepicker' name='startdate' value='" + this.Start.ToShortDateString() + " - " + this.End.ToShortDateString() + "'></div>";
        }


        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            Page.Header.Controls.Add(new LiteralControl(String.Format("<link  href='{0}' rel='stylesheet' type='text/css' />", Page.ClientScript.GetWebResourceUrl(this.GetType(), "HDI.Charts2.css.HDIGantt.css"))));
            if (useDatepicker == true)
            {
                // string firstDate = (from d in this.Daten from c in d select c["Start"].ToDate()).Min().ToString("yyyy-MM-dd");
                // string endDate = (from d in this.Daten from c in d select c["End"].ToDate()).Max().ToString("yyyy-MM-dd");
                Page.Header.Controls.Add(new LiteralControl(String.Format("<script name='datepicker' src='{0}'  type='text/javascript' ></script>", Page.ClientScript.GetWebResourceUrl(this.GetType(), "HDI.Charts2.js.jquery.datepicker.js"))));
                ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "datepicker", @"
$().ready(function()
{
	$('#" + ClientID + @"Diagramm .datepicker').DatePicker({
		format:'d.m.Y',
		date: ['" + this.Start.ToString("dd.MM.yyyy") + "','" + this.End.ToString("dd.MM.yyyy") + @"'],// $('#startdate').val().split(' - '),
		current: '" + this.Start.AddDays(3).ToString("dd.MM.yyyy") + @"',    
		mode:'range',
		calendars:3,
		position: 'bottom',
		onRender: function(date) 
		{
			return {
				disabled: (date.valueOf() < new Date('" + this.Start.ToString("yyyy-MM-dd") + @" 00:00:00').valueOf()  || date.valueOf() > new Date('" + this.End.ToString("yyyy-MM-dd") + @" 00:00:00').valueOf() || (date.getDay()  != 1 && date.getDay()  != 0) )
			}
		},
		onChange: function(formated, dates)
		{

			$('#startdate').val(formated.join(' - '));
			if(dates[0].toDateString() != dates[1].toDateString())
			{  
                var Days = 0; 
				$('#" + ClientID + @"Diagramm tr').each(function(index,ele)
				{


if($(ele).attr('startDate') && $(ele).attr('endDate'))
{
var dateHelper = $(ele).attr('startDate').split('-');
		start = new Date(dateHelper[0], dateHelper[1]-1, dateHelper[2]); 

 dateHelper =$(ele).attr('endDate').split('-');
if(dateHelper.length >= 3)
					end = new Date(dateHelper[0], dateHelper[1]-1, dateHelper[2]);

					if(start > dates[1] || end < dates[0])
					{

						$(ele).addClass('hideDate');
					}else
					{
						$(ele).removeClass('hideDate');
					}
}
				});

				$('#" + ClientID + @"Diagramm .ganttDays td').each(function(index,ele)
				{
					var sDate = $(this).attr('date').split('-');

					var dDate = new Date(sDate[0],sDate[1]-1,sDate[2]);
					if(dDate < dates[0] || dDate > dates[1] )
					{
						$(ele).addClass('hideDate');
                        $('#" + ClientID + @"Diagramm .ganttWeeks td').eq(Math.floor(index/7)+1 ).addClass('hideDate');
						$('#" + ClientID + @"Diagramm tr').each(function(index2,ele2)
						{
							if($(this).attr('startdate'))
							{
								$(this).find('td').eq(index+1).addClass('hideDate');
							}
						});
					}else
					{
						$(ele).removeClass('hideDate');
                        $('#" + ClientID + @"Diagramm .ganttWeeks td').eq(Math.floor(index/7)+1 ).removeClass('hideDate');
                        Days++;
						$('#" + ClientID + @"Diagramm tr').each(function(index2,ele2)
						{
							if($(this).attr('startdate'))
							{
								$(this).find('td').eq(index+1).removeClass('hideDate');
                               
							}
						});
					}
				});
                $('#" + ClientID + @"Diagramm .datepicker').DatePickerHide();
                $('#" + ClientID + @"Diagramm table').css('width',Days * 18  + 100);
			}
		}
	});
});

function test(x, y){ console.log(x+' '+y); return false;}

", true);
                Page.Header.Controls.Add(new LiteralControl(String.Format("<link  href='{0}' rel='stylesheet' type='text/css' />", Page.ClientScript.GetWebResourceUrl(this.GetType(), "HDI.Charts2.css.datepicker.css"))));
            }
        }

        private string search { get; set; }

        private string datepicker { get; set; }


        public bool useDatepicker { get; set; }
        public bool useLegend { get; set; }
        public bool useSearch { get; set; }

    }
}